#include "gate.h"
#include "fruit.h"
#include "orange.h"

#include <fstream>
#include <time.h>

//////////////////////////////////////////////////////////////////////////
void split(const std::string &str, const std::string &delim, std::vector<std::string> &ret)
{
	ret.clear();
	size_t last = 0;
	size_t index = str.find_first_of(delim, last);

	if (index == std::string::npos)
	{
		ret.emplace_back(str);
		return;
	}

	while (index != std::string::npos)
	{
		ret.emplace_back(str.substr(last, index - last));
		last = index + 1;
		index = str.find_first_of(delim, last);
	}

	if (index - last > 0)
	{
		ret.emplace_back(str.substr(last, index - last));
	}
}


std::string replace(const std::string &str, const std::string &to_replace, const std::string &replace)
{
	std::string::size_type pos = 0;
	std::string::size_type srcLen = to_replace.size();
	std::string::size_type desLen = replace.size();
	pos = str.find(to_replace, pos);
	std::string ret = str;
	while ((pos != std::string::npos))
	{
		ret.replace(pos, srcLen, replace);
		pos = ret.find(to_replace, (pos + desLen));
	}
	return std::move(ret);
}


//////////////////////////////////////////////////////////////////////////
void blackList(std::set<std::string>& li)
{
	std::ifstream ifile("ip_blacklist.txt");
	if (!ifile.is_open())
	{
		return;
	}
	std::string line;
	while (true)
	{
		getline(ifile, line);
		line = replace(line, " ", "");
		if (line.find('=') != std::string::npos)
		{
			std::vector<std::string> strs;
			split(line, "=", strs);
			if (strs[1] != "0" && strs[1] != "")
			{
				li.insert(strs[0]);
			}
		}
		else if (!line.empty())
		{
			li.insert(line);
		}
		if (ifile.eof())
		{
			break;
		}
	}
	ifile.close();
}


void setLogName(std::string& log)
{
	time_t tick;
	struct tm tm;
	char s[64];
	tick = time(NULL);
	tm = *localtime(&tick);
	strftime(s, sizeof(s), "%m%d-%H%M", &tm);
	log = s;
	log += ".log";
}


void writeLog(std::ofstream& ofile, unsigned long dwConnID, int order, const char* strip, unsigned char* ptr, int length)
{
	static time_t tick;
	static tm tm;
	tick = time(NULL);
	tm = *localtime(&tick);
	char s[64];
	strftime(s, sizeof(s), "%m%d-%H:%M:%S", &tm);

	static unsigned char c;
	c = ptr[length];
	ptr[length] = 0;
	ofile << s << '\t' << strip << '\t' << order << '\t' << ptr << '\n';
	ptr[length] = c;
	ofile.close();
}


void writeLog(const std::string& logName, unsigned long dwConnID, int order, const char* strip, unsigned char* ptr, int length)
{
	static std::ofstream ofile;
	if (!ofile.is_open())
	{
		ofile.open(logName, std::ios::app);
		if (ofile.is_open())
		{
			writeLog(ofile, dwConnID, order, strip, ptr, length);
		}
	}
	else
	{
		writeLog(ofile, dwConnID, order, strip, ptr, length);
	}
}



const char* getIp(HP_Server pSender, CONNID dwConnID)
{
	unsigned short port;
	return getIp(pSender, dwConnID, port);
}


const char* getIp(HP_Server pSender, CONNID dwConnID, unsigned short& port)
{
	static TCHAR ip[0x20];
	memset(ip, 0, sizeof(ip));
	int length = sizeof(ip) / sizeof(TCHAR);
	if (::HP_Server_GetRemoteAddress(pSender, dwConnID, ip, &length, &port) == FALSE)
	{
		return nullptr;
	}
	return ip;
}



bool checkVersion(const std::string& version, int orderInner, int parameter, char type, const unsigned char* arr, int length)
{
	std::string str((char*)arr, length);
	static char ptr[16];
	memset(ptr, 0, sizeof(ptr));
	sprintf(ptr, "%04d", orderInner);
	str += ptr;
	memset(ptr, 0, sizeof(ptr));
	sprintf(ptr, "%02d", parameter);
	str += ptr;
	memset(ptr, 0, sizeof(ptr));
	sprintf(ptr, "%02d", (int)type);
	str += ptr;
	return version == str;
}


bool checkMatrix(int orderCheck, unsigned char* arr, int iLength)
{
	if (*(int*)(arr + 0x100) != orderCheck)
	{
		return false;
	}
	std::set<unsigned char> cs;
	for (int k = 0; k < 0x100; ++k)
	{
		cs.insert(arr[k]);
	}
	return cs.size() == 0x100;
}


bool checkRegiste(unsigned char* ptr, int length)
{
	for (int k = 0; k < length; ++k)
	{
		const auto& c = ptr[k];
		if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
		{

		}
		else
		{
			return false;
		}
	}
	return true;
}


void eatClient(HP_Server pSender, CONNID dwConnID, int order, const char* arr)
{
	int length = arr == nullptr ? 0 : strlen(arr);
	auto ptr = toClient(order, typeString, (unsigned char*)arr, length);
	auto arr2 = easyApple(ptr, length);
	delete[] ptr;
	if (arr2 == nullptr)
	{
		return;
	}
	::HP_Server_Send(pSender, dwConnID, arr2, length);
	delete[] arr2;
}



void eatChecked(HP_Server pSender, CONNID connectid, unsigned char* arr, int length, const char* strip)
{
	int size = strlen(strip);
	auto ptr = new unsigned char[c21 + size];
	memcpy(ptr, arr, c21);
	memcpy(ptr + c21, strip, size);
	::HP_Server_Send(pSender, connectid, ptr, c21 + size);
	delete[] ptr;
}


void eatRegiste(HP_Server pSender, CONNID connectid, unsigned char* arr, int length, const char* strip)
{
// 	for (int k = 0; k < length; ++k)
// 	{
// 		printf("%d ", (int)arr[k]);
// 	}
// 	printf("\n");
	int size = strlen(strip);
	auto ptr = new unsigned char[length + size];
//	ccc_static_uchar(ptr, size, l);
	memcpy(ptr, arr, c21);
	memcpy(ptr + c21, strip, size);
	memcpy(ptr + c21 + size, arr + c21, length - c21);
// 	for (int k = 0; k < l; ++k)
// 	{
// 		printf("%d ", (int)ptr[k]);
// 	}
// 	printf("\n");
	::HP_Server_Send(pSender,connectid, ptr, length + size);
	delete[] ptr;
}


void pushAiring(std::list<sAir>& airings, CONNID cid, unsigned char* arr, int length)
{
	sAir air;
	air.ids.push(cid);
	air.arr = arr;
	air.length = length;
	airings.push_front(air);
}


void pushAiring(std::list<sAir>& airings, const std::set<CONNID>& cids, unsigned char* arr, int length)
{
	if (cids.empty())
	{
		return;
	}
	sAir air;
	for (const auto& c : cids)
	{
		air.ids.push(c);
	}
	air.arr = arr;
	air.length = length;
	airings.push_front(air);
}


void popAiring(HP_Server pSender, std::list<sAir>& airings)
{
	if (airings.empty())
	{
		return;
	}
	auto& air = airings.back();
	::HP_Server_Send(pSender, air.ids.top(), air.arr, air.length);
	air.ids.pop();
	if (air.ids.empty())
	{
		delete[] air.arr;
		airings.pop_back();
	}
}

